package by.bucha.testproject.xml;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import android.content.Context;
import android.content.res.Resources.NotFoundException;

public class XmlParser {

	private static XmlParser sInstance;

	private XmlParser() {

	}

	public static XmlParser getInstance() {
		if (sInstance == null) {
			sInstance = new XmlParser();
		}
		return sInstance;
	}

	public void parse(String string, final IXmlHandler<?> xmlHandler)
			throws SAXException, NotFoundException, IOException,
			ParserConfigurationException {

		InputStream is = new ByteArrayInputStream(string.getBytes());
		parse(is, xmlHandler);
	}

	public void parse(Context ctx, int rawResource,
			final IXmlHandler<?> xmlHandler) throws SAXException,
			NotFoundException, IOException, ParserConfigurationException {

		InputStream is = ctx.getResources().openRawResource(rawResource);
		parse(is, xmlHandler);

	}

	public void parse(InputStream is, final IXmlHandler<?> xmlHandler)
			throws SAXException, NotFoundException, IOException,
			ParserConfigurationException {

		final SAXParserFactory factory = SAXParserFactory.newInstance();

		final SAXParser xml = factory.newSAXParser();

		XMLReader xmlReader = xml.getXMLReader();

		xmlReader.setContentHandler(new ContentHandler() {

			private StringBuffer mBuffer = new StringBuffer();

			@Override
			public void startPrefixMapping(String prefix, String uri)
					throws SAXException {
			}

			@Override
			public void startElement(String uri, String localName,
					String qName, Attributes atts) throws SAXException {

				mBuffer.setLength(0);
				xmlHandler.startTag(localName, atts);

			}

			@Override
			public void startDocument() throws SAXException {
				xmlHandler.startDocument();
			}

			@Override
			public void skippedEntity(String name) throws SAXException {
			}

			@Override
			public void setDocumentLocator(Locator locator) {
			}

			@Override
			public void processingInstruction(String target, String data)
					throws SAXException {
			}

			@Override
			public void ignorableWhitespace(char[] ch, int start, int length)
					throws SAXException {
			}

			@Override
			public void endPrefixMapping(String prefix) throws SAXException {
			}

			@Override
			public void endElement(String uri, String localName, String qName)
					throws SAXException {

				xmlHandler.endTag(localName, mBuffer.toString());

			}

			@Override
			public void endDocument() throws SAXException {
			}

			@Override
			public void characters(char[] ch, int start, int length)
					throws SAXException {

				String chars = new String(ch, start, length);
				mBuffer.append(chars.trim());

			}
		});
		xmlReader.parse(new InputSource(is));
	}

	public interface IXmlHandler<T> {

		// call if document start.

		void startDocument();

		// call if tag start.

		void startTag(String tagName, Attributes atts);

		// call if tag end.

		void endTag(String tagName, String value);

		// gets result after parsing.

		T getResult();
	}
}
